home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / src.zoo / src / update.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-17  |  7.8 KB  |  300 lines

  1. /*                        Copyright (c) 1988 Bellcore
  2.  *                            All Rights Reserved
  3.  *       Permission is granted to copy or use this program, EXCEPT that it
  4.  *       may not be sold for profit, the copyright notice must be reproduced
  5.  *       on copies, and credit should be given to Bellcore where it is due.
  6.  *       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7.  */
  8. /*    $Header: update.c,v 1.1 89/03/17 08:21:23 sau Exp $
  9.     $Source: /m1/mgr.new/src/RCS/update.c,v $
  10. */
  11. static char    RCSid_[] = "$Source: /m1/mgr.new/src/RCS/update.c,v $$Revision: 1.1 $";
  12.  
  13. /* update a background window */
  14.  
  15. /*
  16.  *       build a clip list
  17.  *    1) find all window edges that intersect with the current window 
  18.  *    2) sort all tops+bottoms then left+rights into increasing order
  19.  *    3) for each rectangular patch, see if it is visible on target window
  20.  *    4) if visible, coellesce patch and keep on a list
  21.  *    update window against clip list
  22.  * 5) run through list, and update each rext that intersects with
  23.  *    the clip region
  24.  */
  25.  
  26. #include "bitmap.h"
  27. #include "defs.h"
  28. #include "clip.h"
  29. #include <stdio.h>
  30.  
  31. #define MAX_COORDS    ((MAXWIN+1)  * 5)    /* educated guess (stab in the dark?) */
  32.  
  33. struct rect_list {                /* list of visible "patches" of obscured window */
  34.     rectangle rect;                /* clipping rectangle */
  35.     struct rect_list *next;        /* next clipping rectangle */
  36.     };
  37.  
  38. static int x[MAX_COORDS];        /* left/right edges of covering windows */
  39. static int y[MAX_COORDS];        /* top/bottom edges of covering windows */
  40.  
  41. /* update an obscured window */
  42.  
  43. update(win, clipp)
  44. register WINDOW *win;
  45. rect    *clipp;
  46.     {
  47.     /* generate clip list */
  48.  
  49.     if (!(W(flags)&W_CLIPDONE)) {
  50.         if (W(clip_list) != NULL) /* free old list (we could reuse it) */
  51.             zap_cliplist(win);
  52.         gen_list(win);
  53.         W(flags) |= W_CLIPDONE;
  54.         }
  55.  
  56.     /* update the window */
  57.  
  58.    do_update(win,clipp);            /* do the update */
  59.     }
  60.  
  61. /* free window's clip list */
  62.  
  63. int
  64. zap_cliplist(win)
  65. WINDOW *win;
  66.     {
  67.     register struct rect_list *list = (struct rect_list *) W(clip_list);
  68.     register struct rect_list *next;
  69.  
  70. #ifdef DEBUG
  71.     dprintf(U)(stderr,"Zapping clip list\r\n");
  72. #endif
  73.     for(;list;list=next) {
  74.         next = list->next;
  75.         free(list);
  76.         }    
  77.     W(clip_list) = NULL;
  78.     }
  79.  
  80. /* generate a clip list */
  81.  
  82. int
  83. gen_list(window)
  84. register WINDOW *window;
  85.    {
  86.  
  87.    register WINDOW *win = window;
  88.    register struct rect_list *list, *prev = (struct rect_list *)0;
  89.    register int x_cnt = 2, y_cnt = 2;
  90.    register int i, j;
  91.    int count = 0;
  92.    int skip;        /* covered by another window - skip patch */
  93.    int hold;        /* hold for coellessing */
  94.  
  95.    int cmp();        /* compare for qsort */
  96.  
  97.    /* build arrays of window coordinates: intersecting win's above win */
  98.  
  99.    x[0] = SUM_BDR + W(x0);
  100.    y[0] = SUM_BDR + W(y0);
  101.    x[1] = SUM_BDR + W(x0) + BIT_WIDE(W(window));
  102.    y[1] = SUM_BDR + W(y0) + BIT_HIGH(W(window));
  103.  
  104.    for(win = active; win != window; win=W(next)) {
  105.       if (!(in_win(win,x[0],y[0],x[1],y[1])))
  106.          continue;
  107.  
  108.       if (W(x0) >= x[0] && W(x0) <= x[1])
  109.          x[x_cnt++] = W(x0);
  110.  
  111.       if (W(y0) >= y[0] && W(y0) <= y[1])
  112.          y[y_cnt++] = W(y0);
  113.  
  114.       if (W(x0) + BIT_WIDE(W(border)) >= x[0] &&
  115.                W(x0) + BIT_WIDE(W(border)) <= x[1])
  116.          x[x_cnt++] = W(x0) + BIT_WIDE(W(border));
  117.  
  118.       if (W(y0) + BIT_HIGH(W(border)) >= y[0] &&
  119.                W(y0) + BIT_HIGH(W(border)) <= y[1])
  120.          y[y_cnt++] = W(y0) + BIT_HIGH(W(border));
  121.       
  122.       if (y_cnt >= MAX_COORDS || x_cnt >= MAX_COORDS)
  123.          break;
  124.       }
  125.  
  126.    /* sort window coordinate lists */
  127.  
  128.    qsort(x,x_cnt,sizeof(int),cmp);
  129.    qsort(y,y_cnt,sizeof(int),cmp);
  130.  
  131.    x_cnt--;
  132.    y_cnt--;
  133.  
  134.    /* build list of covering rectangles */
  135.  
  136.    for(j=0; j<y_cnt; j++) {
  137.  
  138.       if (y[j] == y[j+1])    /* avoid zero-height patches */
  139.          continue;
  140.  
  141.       for(hold=x_cnt,i=0; i<x_cnt; i++) {
  142.  
  143.          if (x[i] == x[i+1])    /* avoid zero-width patches */
  144.             continue;
  145.  
  146.             /* see if patch is visible */
  147.  
  148.          for(skip=0,win=active; win!=window; win=W(next))
  149.             if (in_win(win, x[i], y[j], x[i+1], y[j+1])) {
  150.                skip++;
  151.                break;
  152.                }
  153.  
  154.             /* visible, add patch to list, or append to previous patch */
  155.  
  156.          if (!skip)  {
  157.                 if (i == hold) {        /* coel. across */
  158.                     list->rect.wide += x[i+1] - x[i];
  159.                     hold++;
  160.                     }
  161.                 else {    /* flush held rect */
  162.                     count++;        /* only for debugging */
  163.                     list = (struct rect_list *) alloc(sizeof(struct rect_list));
  164.                     list->rect.x = x[i] - W(x0);
  165.                     list->rect.y = y[j] - W(y0);
  166.                     list->rect.wide = x[i+1] - x[i];
  167.                     list->rect.high = y[j+1] - y[j];
  168.                     list -> next = NULL;
  169.                     if (prev)
  170.                         prev -> next = list;
  171.                     if (!W(clip_list))    /* set initial rectangle */
  172.                         W(clip_list) = (char *) list;
  173.                     prev = list;
  174.                     hold = i+1;                /* next 'i' to check for coell. */
  175.                     }
  176.             }
  177.          }
  178.       }
  179.  
  180. /* look at rect list    DEBUG code, commented out!
  181.  
  182.     for(list=(struct rect_list *) W(clip_list);list;list = list->next) {
  183.         int    x = list->rect.x,
  184.             y = list->rect.y,
  185.             wide = list->rect.wide,
  186.             high = list->rect.high;
  187.         in_mouseoff( x, y, wide, high );
  188.         bit_blit(W(border), x, y, wide, high, BIT_NOT(BIT_DST),0L,0,0);
  189.         dprintf(U)(stderr,"  Rect %d,%d  %dx%d\n", x, y, wide, high );
  190.         getchar();
  191.         bit_blit(W(border), x, y, wide, high, BIT_NOT(BIT_DST),0L,0,0);
  192.         MOUSE_ON(mousex,mousey);
  193.         }
  194. DEBUG code, commented out! */
  195.  
  196. #ifdef DEBUG
  197.     dprintf(U)(stderr,"%s: Built clip list (%d)\r\n",W(tty),count);
  198. #endif
  199.  
  200.     return(0);    /* I'll think of something */
  201.    }
  202.  
  203. /* update obscured window */
  204.  
  205. int
  206. do_update(win,clipp)    
  207. register WINDOW *win;    /* window to update */
  208. rect *clipp;          /* region of window to update (window coords) */
  209.     {
  210.    register struct rect_list *list;    /* list of rectangle to clip to */
  211.    register rectangle *got;        /* intersecting region */
  212.    rectangle *got_int();        /* finds intersecting rectangle */
  213.  
  214. #ifdef DEBUG
  215.     dprintf(*)(stderr,"Updating background window to %d,%d => %d,%d\r\n",
  216.         clipp->x1,clipp->y1,clipp->x2,clipp->y2);
  217. #endif
  218.  
  219.     for(list=(struct rect_list *)W(clip_list);list;list = list->next) {
  220.         if (got = got_int(&(list->rect),clipp)) {
  221.             register int    x = got->x,
  222.                     y = got->y,
  223.                     wide = got->wide,
  224.                     high = got->high;
  225.             in_mouseoff( x + W(x0), y + W(y0), wide, high );
  226.             bit_blit(W(border),x,y,wide,high,BIT_SRC,W(save),x,y);
  227.             MOUSE_ON(mousex,mousey);
  228.             }
  229.         }
  230.     }
  231.  
  232. /* find the intersection of 2 rectangles */
  233.  
  234. rectangle *
  235. got_int(r1,r2)
  236. register rectangle *r1;        /* rect 1 */
  237. register rect *r2;            /* other rect   (should both be same struct) */
  238.     {
  239.     static rectangle result;
  240.  
  241.     result.x = Max(r1->x,r2->x1+SUM_BDR);
  242.     result.y = Max(r1->y,r2->y1+SUM_BDR);
  243.     result.wide = Min(r1->x + r1->wide, r2->x2+SUM_BDR) - result.x;
  244.     result.high = Min(r1->y + r1->high, r2->y2+SUM_BDR) - result.y;
  245.  
  246.     if (result.wide > 0 && result.high > 0 )
  247.       return(&result);
  248.     else
  249.         return((rectangle *) 0);
  250.     }
  251.  
  252. /* see if mouse in rectangle, if so turn the mouse off */
  253.  
  254. in_mouseoff(x0,y0,wide,high)
  255. register int x0,y0,wide,high;
  256.    {
  257.    if( !( x0 > mousex+16 || y0 > mousey+16 ||
  258.         x0+wide < mousex || y0+high < mousey))
  259.     MOUSE_OFF(mousex,mousey);
  260.    }
  261.          
  262. /* see if rectangle in window */
  263.  
  264. int
  265. in_win(win,x0,y0,x1,y1)
  266. register WINDOW *win;
  267. register x0,y0,x1,y1;
  268.    {
  269.    return(
  270.       W(x0) + BIT_WIDE(W(border)) <= x0 ||
  271.       x1 <= W(x0) ||
  272.       W(y0) + BIT_HIGH(W(border)) <= y0 ||
  273.       y1 <= W(y0)
  274.    ?  0  :  1);
  275.    }
  276.  
  277. /* compare for qsort */
  278.  
  279. int
  280. cmp(x,y)
  281. int *x, *y;
  282.    {
  283.    return( *x - *y);
  284.    }
  285.  
  286. /* invalidate clip list for all windows affected by 'window' */
  287.  
  288. clip_bad(window)
  289. register WINDOW *window;        /* this window has changed */
  290.     {
  291.     register WINDOW *win;        /* working window */
  292.  
  293.     /* invalidate all intersecting window clip lists below this one */
  294.  
  295.     window->flags &= ~W_CLIPDONE;        /* invalidate clip list */
  296.    for(win=window->next;win != (WINDOW *) 0;win=W(next))
  297.         if (intersect(win,window)) 
  298.             W(flags) &= ~W_CLIPDONE;        /* invalidate clip list */
  299.     }
  300.